// ...existing code...
#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#include <sstream>
#include <fstream>
#include "Logger.hpp"
#include "Session.hpp"

static const std::string linesep = "\r\n";
static const std::string innersep1 = " ";
static const std::string innersep2 = ": ";
static const std::string suffixsep = ".";

static const std::string webroot = "./wwwroot";
static const std::string defaulthome = "index.html";
static const std::string err_html = "404.html";

//  Content-Type Content-Length Referer

// 定制协议
class HttpRequest
{
private:
    std::string ReadOneLine(std::string &reqstr, bool *status)
    {
        auto pos = reqstr.find(linesep);
        if (pos == std::string::npos)
        {
            *status = false;
            return std::string();
        }
        *status = true;
        auto line = reqstr.substr(0, pos);
        // 修复：应擦除包含分隔符的长度，而不是 line.size()
        reqstr.erase(0, pos + linesep.size());

        return line;
    }

    void ParseReqline(std::string &reqline)
    {
        std::stringstream ss(reqline);
        ss >> _method >> _uri >> _http_version;
    }

    void BulidKV(std::string &reqline, std::string *K, std::string *V)
    {
        auto pos = reqline.find(innersep2);
        if (pos == std::string::npos)
        {
            *K = *V = std::string();
            return;
        }
        *K = reqline.substr(0, pos);
        *V = reqline.substr(pos + innersep2.size());
    }

public:
    HttpRequest()
    {
    }
    void Serializ(std::string *out)
    {
        // 浏览器自己做好了
    }

    //  认为reqstr已经是一个完整的报文了
    bool Deserialize(std::string &reqstr)
    {

        bool status;
        std::string reqline = ReadOneLine(reqstr, &status);
        if (!status)
            return false;

        ParseReqline(reqline);
        LOG(LogLevel::DEBUG) << "_method: " << _method;
        LOG(LogLevel::DEBUG) << "_uri: " << _uri;
        LOG(LogLevel::DEBUG) << "_http_version: " << _http_version;

        // 解析 headers，直到空行
        while (true)
        {
            reqline = ReadOneLine(reqstr, &status);
            if (!status)
            {
                return false; // 数据不完整
            }
            if (reqline.empty())
            {
                // 遇到空行，结尾
                _blank_line = linesep;
                break;
            }
            std::string K, V;
            BulidKV(reqline, &K, &V);
            if (!K.empty())
            {
                _req_headers.emplace(K, V);
            }
        }

        for (auto &elem : _req_headers)
        {
            LOG(LogLevel::DEBUG) << elem.first << "# " << elem.second;
        }

        // 剩余部分视为 body
        _req_body = reqstr;

        _path = webroot;
        _path += _uri;
        if (_uri == "/")
        {
            if (_path.back() != '/')
                _path += '/';
            _path += defaulthome;
        }

        return true;
    }
    std::string Path()
    {
        return _path;
    }
    std::unordered_map<std::string, std::string> Head()
    {
        return _req_headers;
    }
    std::string Suffix()
    {
        if (_path.empty())
        {
            return std::string();
        }
        else
        {
            auto pos = _path.rfind(suffixsep);
            if (pos == std::string::npos)
                return std::string();
            else
                return _path.substr(pos); // 后缀
        }
    }
    void SetPath(const std::string &path)
    {
        _path = path;
    }
    ~HttpRequest()
    {
    }

private:
    std::string _method;
    std::string _uri;
    std::string _http_version;
    std::unordered_map<std::string, std::string> _req_headers;
    std::string _blank_line;
    std::string _req_body;

    std::string _path;
};

class HttpRespone
{
private:
    std::string Code2Desc(int code)
    {
        switch (code)
        {
        case 200:
            return "OK";
            break;
        case 400:
            return "Bad Request";
            break;
        case 404:
            return "Not Found";
            break;
        case 301:
            return "Moved Permanently";
            break;
        case 302:
            return "See Other";
            break;
        default:
            return "";
            break;
        }
    }

public:
    HttpRespone() : _http_version("HTTP/1.1"), _blank_line(linesep), _code(200)
    {
    }
    std::string Serializ()
    {
        // 确保 Content-Length 存在
        if (_rep_headers.find("Content-Length") == _rep_headers.end())
        {
            _rep_headers["Content-Length"] = std::to_string(_rep_body.size());
        }
        std::string respstr = _http_version + innersep1 + std::to_string(_code) +
                              innersep1 + _desc + linesep;

        for (auto &elem : _rep_headers)
        {
            std::string line = elem.first + innersep2 + elem.second + linesep;
            respstr += line;
        }
        for (auto &cookie : _cookie)
        {
            respstr += cookie;
            respstr += linesep;
        }
        respstr += _blank_line;
        respstr += _rep_body;

        return respstr;
    }

    void Deserialize(std::string &in)
    {
        // 浏览器自己做好了
    }
    bool ReadContent(const std::string &path)
    {
        // 以二进制方式读取
        std::ifstream in(path, std::ios::binary);
        if (!in.is_open())
        {
            LOG(LogLevel::WARNING) << "file open error";
            _rep_body.clear();
            return false;
        }
        in.seekg(0, in.end);
        std::streamoff filesize = in.tellg(); // 获取文件大小
        in.seekg(0, in.beg);
        if (filesize > 0)
        {
            _rep_body.resize(static_cast<size_t>(filesize));
            in.read(&(_rep_body[0]), static_cast<std::streamsize>(filesize));
        }
        else
        {
            _rep_body.clear();
        }
        in.close();
        return true;
    }
    void SetCode(int code)
    {
        if (code >= 100 && code < 600)
        {
            _code = code;
            _desc = Code2Desc(code);
        }
        else
        {
            LOG(LogLevel::ERROR) << "非法的状态码";
        }
    }

    bool SetHeader(const std::string &key, const std::string &value)
    {
        _rep_headers[key] = value;
        return true;
    }

    bool SetCookie(const std::string &key, const std::string &value)
    {
        std::string cookie = key;
        cookie += innersep2;
        cookie += value;
        _cookie.push_back(cookie);
        return true;
    }
    ~HttpRespone()
    {
    }

private:
    std::string _http_version;
    int _code;
    std::string _desc;
    std::unordered_map<std::string, std::string> _rep_headers;
    std::string _blank_line;
    std::string _rep_body;

    std::vector<std::string> _cookie;
};

class Http
{
    // ...existing code...
    std::string Suffix2Desc(const std::string &suffix)
    {
        if (suffix == ".html")
        {
            return "text/html";
        }
        else if (suffix == ".css")
        {
            return "text/css";
        }
        else if (suffix == ".jpg" || suffix == ".jpeg")
        {
            return "image/jpeg";
        }
        else if (suffix == ".png")
        {
            return "image/png";
        }
        else if (suffix == ".js")
        {
            return "application/javascript";
        }
        else if (suffix == ".json")
        {
            return "application/json";
        }
        else
        {
            return "application/octet-stream";
        }
    }
    // ...existing code...
public:
    Http()
    {
    }
    std::string HandlerRequest(std::string &reqstr)
    {

        std::string respstr;
        HttpRequest req;
        if (req.Deserialize(reqstr))
        {
            HttpRespone resp;
            if (req.Path() == "./wwwroot/redir")
            {
                resp.SetCode(302);
                resp.SetHeader("Location", "sss.html");
            }
            else if (resp.ReadContent(req.Path()))
            {
                std::string suffix = req.Suffix();
                std::string mime_type_value = Suffix2Desc(suffix); // 资源后缀，转成Content-Type
                resp.SetHeader("Content-Type", mime_type_value);
                resp.SetCode(200);
            }
            else
            {
                std::string error_html = webroot + "/" + err_html;
                req.SetPath(error_html);
                resp.ReadContent(req.Path());
                std::string suffix = req.Suffix();
                std::string mime_type_value = Suffix2Desc(suffix); // 资源后缀，转成Content-Type
                resp.SetCode(404);
            }
            respstr = resp.Serializ();
        }

        return respstr;
    }
    ~Http()
    {
    }
};
// ...existing code...